var images = [
  "https://cdn.pixabay.com/photo/2016/10/13/00/03/girl-1736419__340.jpg",
  "https://img.freepik.com/free-photo/young-sexy-woman-black-lingerie-posing-bed_273443-2462.jpg",
  "https://cdn.pixabay.com/photo/2018/03/06/22/57/portrait-3204843_1280.jpg",
  "https://cdn.pixabay.com/photo/2024/04/14/03/38/woman-8694743_960_720.png",
  "https://img.freepik.com/free-photo/fashion-portrait-young-rich-stylish-european-woman-black-trendy-swimsuit-sunglasses-lace-cape-outside-villa-tropical-background-sunset-warm-light_343596-3686.jpg",
  "https://cdn.pixabay.com/photo/2017/09/21/07/47/girl-2771001__340.jpg",
  "https://cdn.pixabay.com/photo/2018/03/12/12/32/woman-3219507__340.jpg",
  "https://img.freepik.com/free-photo/pretty-young-woman-outdoor_624325-3094.jpg",
];

const ulEles = document.querySelector(".carousel .wrap ul");
const frag = document.createDocumentFragment();
for (let i = 0; i < images.length; i++) {
  const li = document.createElement("li");
  const img = document.createElement("img");
  img.src = images[i];
  li.appendChild(img);
  frag.appendChild(li);
}
ulEles.appendChild(frag);

class HoverCarousel {
  // 构造函数，初始化DOM元素和设置
  constructor(elm, settings) {
    this.DOM = {
      scope: elm,
      wrap: elm.querySelector("ul").parentNode,
    };

    // 默认设置
    this.settings = {
      sensitivity: 2,
      ...settings,
    };

    // 容器宽度
    this.containerWidth = 0;
    // 滚动宽度
    this.scrollWidth = 0;
    // 从左边的位置
    this.posFromLeft = 0; // Stripe position from the left of the screen
    // 相对鼠标位置
    this.stripePos = 0; // When relative mouse position inside the thumbs stripe
    // 动画
    this.animated = null;
    // 回调函数
    this.callbacks = {};

    // 初始化
    this.init();
  }

  // 初始化
  init() {
    this.bind();
  }

  // 销毁
  destroy() {
    this.DOM.scope.removeEventListener(
      "mouseenter",
      this.callbacks.onMouseEnter
    );
    this.DOM.scope.removeEventListener("mousemove", this.callbacks.onMouseMove);
  }

  // 绑定事件
  bind() {
    // 绑定鼠标进入事件
    this.callbacks.onMouseEnter = this.onMouseEnter.bind(this);
    // 绑定鼠标移动事件
    this.callbacks.onMouseMove = (e) => {
      // 如果鼠标移动动画帧存在，则取消
      if (this.mouseMoveRAF) cancelAnimationFrame(this.mouseMoveRAF);

      // 请求鼠标移动动画帧
      this.mouseMoveRAF = requestAnimationFrame(this.onMouseMove.bind(this, e));
    };

    // 监听鼠标进入事件
    this.DOM.scope.addEventListener("mouseenter", this.callbacks.onMouseEnter);
    // 监听鼠标移动事件
    this.DOM.scope.addEventListener("mousemove", this.callbacks.onMouseMove);
  }

  onMouseEnter(e) {
    this.nextMore = this.prevMore = false; // reset

    // 获取容器的宽度
    this.containerWidth = this.DOM.wrap.clientWidth;
    // 获取容器的滚动宽度
    this.scrollWidth = this.DOM.wrap.scrollWidth;
    // 获取容器的内边距
    this.padding = 0.2 * this.containerWidth;
    // 获取容器的左边距
    this.posFromLeft = this.DOM.wrap.getBoundingClientRect().left;
    // 获取鼠标在容器的位置
    var stripePos = e.pageX - this.padding - this.posFromLeft;
    // 计算鼠标在容器中的位置比例
    this.pos = stripePos / (this.containerWidth - this.padding * 2);
    // 计算滚动位置
    this.scrollPos = (this.scrollWidth - this.containerWidth) * this.pos;

    // 设置滚动行为为平滑滚动
    this.DOM.wrap.style.scrollBehavior = "smooth";

    // 如果滚动位置小于0，则设置为0
    if (this.scrollPos < 0) this.scrollPos = 0;

    // 如果滚动位置大于容器的滚动宽度减去容器的宽度，则设置为容器的滚动宽度减去容器的宽度
    if (this.scrollPos > this.scrollWidth - this.containerWidth)
      this.scrollPos = this.scrollWidth - this.containerWidth;

    // 设置容器的滚动位置
    this.DOM.wrap.scrollLeft = this.scrollPos;
    this.DOM.scope.style.setProperty(
      "--scrollWidth",
      (this.containerWidth / this.scrollWidth) * 100 + "%"
    );
    this.DOM.scope.style.setProperty(
      "--scrollLeft",
      (this.scrollPos / this.scrollWidth) * 100 + "%"
    );

    // lock UI until mouse-enter scroll is finihsed, after aprox 200ms
    clearTimeout(this.animated);
    this.animated = setTimeout(() => {
      this.animated = null;
      this.DOM.wrap.style.scrollBehavior = "auto";
    }, 200);

    return this;
  }

  // 鼠标移动事件
  onMouseMove(e) {
    // 如果正在动画中，则返回
    if (this.animated) return;

    // 计算滚动条的宽度与容器宽度的比例
    this.ratio = this.scrollWidth / this.containerWidth;

    // 计算鼠标在滚动条上的位置
    var stripePos = e.pageX - this.padding - this.posFromLeft;

    // 如果鼠标位置小于0，则将其设置为0
    if (stripePos < 0) stripePos = 0;

    // 计算滚动条的位置
    this.pos = stripePos / (this.containerWidth - this.padding * 2);

    // 计算滚动位置
    this.scrollPos = (this.scrollWidth - this.containerWidth) * this.pos;

    // 设置DOM.wrap的scrollLeft属性为this.scrollPos
    this.DOM.wrap.scrollLeft = this.scrollPos;

    // 如果this.scrollPos小于this.scrollWidth - this.containerWidth，则设置DOM.scope的--scrollLeft属性为(this.scrollPos / this.scrollWidth) * 100 + "%"
    if (this.scrollPos < this.scrollWidth - this.containerWidth)
      this.DOM.scope.style.setProperty(
        "--scrollLeft",
        (this.scrollPos / this.scrollWidth) * 100 + "%"
      );

    // 设置this.prevMore为this.DOM.wrap.scrollLeft是否大于0
    this.prevMore = this.DOM.wrap.scrollLeft > 0;
    // 设置this.nextMore为this.scrollWidth - this.containerWidth - this.DOM.wrap.scrollLeft是否大于5
    this.nextMore =
      this.scrollWidth - this.containerWidth - this.DOM.wrap.scrollLeft > 5;

    // 设置DOM.scope的data-at属性为(prevMore ? "left " : " ") + (this.nextMore ? "right" : "")
    this.DOM.scope.setAttribute(
      "data-at",
      (this.prevMore ? "left " : " ") + (this.nextMore ? "right" : "")
    );
  }
}

const carouselEle = document.querySelector(".carousel");
new HoverCarousel(carouselEle);
